psp.o mxf.o holux.o garmin.o ozi.o tmpro.o dna.o tpg.o gpsdrive.o \
xcsv.o xmapwpt.o gcdb.o
+FILTERS=position.o duplicate.o
+
JEEPS=jeeps/gpsapp.o jeeps/gpscom.o \
jeeps/gpsmath.o jeeps/gpsmem.o \
jeeps/gpsprot.o jeeps/gpsread.o \
COLDSYNC=coldsync/util.o coldsync/pdb.o
-OBJS=main.o queue.o route.o waypt.o util.o vecs.o mkshort.o csv_util.o \
- $(COLDSYNC) $(GARMIN) $(JEEPS) $(FMTS)
+OBJS=main.o queue.o route.o waypt.o filter_vecs.o util.o vecs.o mkshort.o csv_util.o \
+ $(COLDSYNC) $(GARMIN) $(JEEPS) $(FMTS) $(FILTERS)
.c.o:
$(CC) -c $(CFLAGS) $< -o $@
jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
util.o: util.c defs.h queue.h
vecs.o: vecs.c defs.h queue.h
+filter_vecs.o: filter_vecs.c defs.h queue.h
+position.o:position.c defs.h
waypt.o: waypt.c defs.h queue.h
xcsv.o: xcsv.c defs.h queue.h csv_util.h
xmapwpt.o: xmapwpt.c defs.h queue.h csv_util.h
http://vip.hyperusa.com/~dougs/geocachingdb/geocachingdb.htm
+DATA FILTERS
+
+ GPSBabel supports data filtering. Data filters are invoked from
+ the command line via the '-x' option. It should be noted that
+ data filters are invoked in the order they appear on the command
+ line and can be used in intermittently between several variations
+ of input and output functions. It should also be noted that
+ filtering data from different input types can sometimes produce
+ undesirable results due to differences in the native data formats.
+
+
+ POSITION
+
+ The position filter is designed to remove points based on their
+ proximity to each other. Distances can be passed on the command
+ line by passing the distance=XXX option to the filter. Distance
+ options may be expressed in feet (distance=3f) or meters
+ (distance=1m). The default is zero feet, essentially a duplicate
+ position.
+
+ For example:
+
+ gpsbabel -i geo -f 1.loc -f 2.loc -x position,distance=1f \
+ -o mapsend -F 3.wpt
+
+ would remove multiple points that are within 1 foot of each other,
+ leaving just one.
+
+
+ DUPLICATE
+
+ The duplicate filter is designed to remove duplicate points based
+ on their shortname (traditionally a waypoint's name on the GPS
+ receiver), and/or their location (to a precision of 6 decimals).
+ This filter supports two options, "shortname" and "location".
+ Generally, at least one of these options is REQUIRED. For example:
+
+ gpsbabel -i gpx -f 1.gpx -f 2.gpx -x duplicate,location,shortname \
+ -o gpx -F merged_with_no_dupes.gpx
+
+ would remove points that have duplicate shortnames *AND* duplicate
+ locations. The result would be a GPX file that more than likely
+ contains only unique points and point data.
+
+
COMMON USAGE
Invocation was meant to be flexible. Unfortunately, that can
typedef void (*ff_write) (void);
char * get_option(const char *iarglist, const char *argname);
+typedef void (*filter_init) (char const *);
+typedef void (*filter_process) (void);
+typedef void (*filter_deinit) (void);
+
void fprintdms(FILE *, const coord *, int);
typedef void (*waypt_cb) (const waypoint *);
arglist_t *args;
} ff_vecs_t;
+typedef struct filter_vecs {
+ filter_init f_init;
+ filter_process f_process;
+ filter_deinit f_deinit;
+} filter_vecs_t;
+
void waypt_init(void);
void route_init(void);
void waypt_disp(const waypoint *);
__attribute__ ((__format__ (__printf__, 1, 2)))
#endif
;
+
ff_vecs_t *find_vec(char *, char **);
void disp_vecs(void);
void disp_formats(void);
void printposn(const coord *c, int is_lat);
+filter_vecs_t * find_filter_vec(char *, char **);
+void disp_filters(void);
+void disp_filter_vecs(void);
+
void *xcalloc(size_t nmemb, size_t size);
void *xmalloc(size_t size);
char *xstrdup(const char *s);
--- /dev/null
+/*
+ Describe vectors containing filter operations.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include <stdio.h>
+#include "defs.h"
+
+typedef struct {
+ filter_vecs_t *vec;
+ const char *name;
+ const char *desc;
+} fl_vecs_t;
+
+extern filter_vecs_t position_vecs;
+extern filter_vecs_t duplicate_vecs;
+
+static
+fl_vecs_t filter_vec_list[] = {
+ {
+ &position_vecs,
+ "position",
+ "Remove Points Within Distance",
+ },
+ {
+ &duplicate_vecs,
+ "duplicate",
+ "Remove Duplicates",
+ },
+ {
+ NULL,
+ NULL,
+ NULL
+ }
+};
+
+filter_vecs_t *
+find_filter_vec(char *const vecname, char **opts)
+{
+ fl_vecs_t *vec = filter_vec_list;
+ char *v = xstrdup(vecname);
+ char *svecname = strtok(v, ",");
+
+ while (vec->vec) {
+ if (strcmp(svecname, vec->name) == 0) {
+ char * res = strchr(vecname, ',');
+ if (res)
+ *opts = strchr(vecname, ',')+1;
+ else
+ *opts = NULL;
+ free(v);
+ return vec->vec;
+ }
+ vec++;
+ }
+ free(v);
+ return NULL;
+}
+
+/*
+ * Display the available formats in a format that's easy for humans to
+ * parse for help on available command line options.
+ */
+void
+disp_filter_vecs(void)
+{
+ fl_vecs_t *vec;
+ for (vec = filter_vec_list; vec->vec; vec++) {
+ printf(" %-20.20s %-50.50s\n",
+ vec->name, vec->desc);
+ }
+}
+
+/*
+ * Display the available formats in a format that's easy to machine
+ * parse. Typically invoked by programs like graphical wrappers to
+ * determine what formats are supported.
+ */
+void
+disp_filters(void)
+{
+ fl_vecs_t *vec;
+ for (vec = filter_vec_list; vec->vec; vec++) {
+ printf("%s\t%s\n", vec->name, vec->desc);
+ }
+}
{
struct tm *tm = gmtime(&timep);
+ if (!tm)
+ return;
+
fprintf(ofd, "<time>%02d-%02d-%02dT%02d:%02d:%02dZ</time>\n",
tm->tm_year+1900,
tm->tm_mon+1,
);
disp_vecs();
+ printf("\nSupported data filters:\n");
+ disp_filter_vecs();
}
int argn;
ff_vecs_t *ivecs = NULL;
ff_vecs_t *ovecs = NULL;
+ filter_vecs_t *fvecs = NULL;
char *fname = NULL;
char *ofname = NULL;
char *ivec_opts = NULL;
char *ovec_opts = NULL;
+ char *fvec_opts = NULL;
global_opts.objective = wptdata;
case 'r':
global_opts.objective = rtedata;
break;
+ case 'x':
+ optarg = argv[argn][2]
+ ? argv[argn]+2 : argv[++argn];
+
+ fvecs = find_filter_vec(optarg, &fvec_opts);
+
+ if (fvecs) {
+ fvecs->f_init(fvec_opts);
+ fvecs->f_process();
+ fvecs->f_deinit();
+ }
+ break;
case 'D':
optarg = argv[argn][2]
? argv[argn]+2 : argv[++argn];
case '^':
disp_formats();
exit(0);
+ case '%':
+ disp_filters();
+ exit(0);
case 'h':
case '?':
usage(argv[0]);
--- /dev/null
+/*
+ Distance Between Points Filter
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+#include <stdio.h>
+#include <math.h>
+#include "defs.h"
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+extern queue waypt_head;
+
+static double pos_dist;
+
+static double
+gc_distance(double lat1, double lon1, double lat2, double lon2)
+{
+ double rlat1, rlat2, rlon1, rlon2;
+
+ /* convert to radians */
+ rlat1 = (lat1 * M_PI) / 180.0;
+ rlon1 = (lon1 * M_PI) / 180.0;
+ rlat2 = (lat2 * M_PI) / 180.0;
+ rlon2 = (lon2 * M_PI) / 180.0;
+
+ return (acos((sin(rlat1) * sin(rlat2)) +
+ (cos(rlat1) * cos(rlat2) * cos(rlon1 - rlon2))));
+}
+
+static int
+position_comp(const void * a, const void * b)
+{
+ const waypoint *x1 = *(waypoint **)a;
+ const waypoint *x2 = *(waypoint **)b;
+ double latdiff, londiff, max;
+
+ /*
+ * this compare makes the assumption that things will fall into
+ * order by declaring their biggest single axial difference.
+ * It is much less math than distance and bearing from some random
+ * point.
+ */
+
+ londiff = (x1->position.longitude.degrees -
+ x2->position.longitude.degrees) * 1000000.0;
+ latdiff = (x1->position.latitude.degrees -
+ x2->position.latitude.degrees) * 1000000.0;
+
+ max = fabs(londiff) >= fabs(latdiff) ? floor(londiff) : floor(latdiff);
+
+ if (max < 0)
+ return (-1);
+ else if (max > 0)
+ return (1);
+
+ return(0);
+}
+
+void
+position_process(void)
+{
+ queue * elem, * tmp;
+ waypoint ** comp;
+ double dist;
+ int i, wc;
+
+ wc = waypt_count();
+
+ comp = xcalloc(wc, sizeof(*comp));
+
+ i = 0;
+
+ QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
+ comp[i] = (waypoint *)elem;
+ i++;
+ }
+
+ qsort(comp, wc, sizeof(waypoint *), position_comp);
+
+ for (i = 0 ; i < (wc - 1) ; i++) {
+ dist = gc_distance(comp[i]->position.latitude.degrees,
+ comp[i]->position.longitude.degrees,
+ comp[i+1]->position.latitude.degrees,
+ comp[i+1]->position.longitude.degrees);
+
+ /* convert radians to integer feet */
+ dist = (int)((((dist * 180.0 * 60.0) / M_PI) / 1.1516) * 5280.0);
+
+ if (dist <= pos_dist)
+ waypt_del(comp[i]);
+ }
+
+ if (comp)
+ free (comp);
+}
+
+void
+position_init(const char *args) {
+ char *fm;
+ const char *p;
+
+ p = get_option(args, "distance");
+
+ if (p) {
+ pos_dist = strtod(p, &fm);
+
+ if ((*fm == 'm') || (*fm == 'M')) {
+ /* distance is meters */
+ pos_dist *= 3.2802;
+ }
+ }
+}
+
+void
+position_deinit(void) {
+}
+
+filter_vecs_t position_vecs = {
+ position_init,
+ position_process,
+ position_deinit
+};